﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NLite.Reflection;
using System.Reflection;
using System.Data;
using System.Collections;
using System.Linq.Expressions;
using NLite.Validation;

namespace NLite.Mapping
{
  
    /// <summary>
    /// 映射引擎接口
    /// </summary> 
    [Contract]
    public interface IMappingEngine
    {
        /// <summary>
        /// 得到映射器注册表
        /// </summary>
        IMapperRegistry MapperRegistry { get; }
        /// <summary>
        /// 得到映射器工厂注册表
        /// </summary>
        IMapperFactoryRegistry FactoryRegistry { get;}
        /// <summary>
        /// 创建映射器
        /// </summary>
        /// <typeparam name="TFrom"></typeparam>
        /// <typeparam name="TTo"></typeparam>
        /// <returns></returns>
        IMapper<TFrom, TTo> CreateMapper<TFrom, TTo>();
    }

    /// <summary>
    /// 映射器接口
    /// </summary>
    public interface IMapper
    {
        /// <summary>
        /// 得到映射器元数据信息
        /// </summary>
        IMapperInfo Info { get; }

        IValidationResult State { get; }

        /// <summary>
        /// 把from对象映射到to对象中
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        void Map(ref object from,ref object to);
    }

    /// <summary>
    /// 映射器注册表接口
    /// </summary>
    [Contract]
    public interface IMapperRegistry : IDictionary<string, IMapper> { }

    /// <summary>
    /// 映射器工厂接口
    /// </summary>
    public interface IMapperFactory
    {
        /// <summary>
        /// 是否支持fromType到toType的映射
        /// </summary>
        /// <param name="fromType"></param>
        /// <param name="toType"></param>
        /// <returns></returns>
        bool IsMatch(Type fromType, Type toType);

        /// <summary>
        /// 创建fromType到toType的映射器
        /// </summary>
        /// <param name="fromType"></param>
        /// <param name="toType"></param>
        /// <returns></returns>
        IMapper Create(Type fromType, Type toType);
    }

    /// <summary>
    /// 映射器工厂注册表
    /// </summary>
    [Contract]
    public interface IMapperFactoryRegistry : IDictionary<int, IMapperFactory>
    {
    }

  
    /// <summary>
    /// 泛型映射器接口
    /// </summary>
    /// <typeparam name="TFrom"></typeparam>
    /// <typeparam name="TTo"></typeparam>
    public interface IMapper<TFrom, TTo>
    {
        /// <summary>
        /// 得到映射器元数据信息
        /// </summary>
        IMapperInfo Info { get; }

        /// <summary>
        /// 
        /// </summary>
        IValidationResult State { get; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="flag"></param>
        /// <returns></returns>
        IMapper<TFrom, TTo> IgnoreCase(bool flag);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="flag"></param>
        /// <returns></returns>
        IMapper<TFrom, TTo> IgnoreUnderscore(bool flag);
      
        /// <summary>
        /// 
        /// </summary>
        /// <param name="destinationMember"></param>
        /// <param name="memberOptions"></param>
        /// <returns></returns>
        IMapper<TFrom, TTo> ForMember(Expression<Func<TTo,object>> destinationMember,Func<TFrom,object> memberOptions);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="member"></param>
        /// <returns></returns>
        IMapper<TFrom, TTo> IgnoreSourceMember(Expression<Func<TFrom, object>> member);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="member"></param>
        /// <returns></returns>
        IMapper<TFrom, TTo> IgnoreDestinationMember(Expression<Func<TTo, object>> member);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        IMapper<TFrom, TTo> IgnoreSourceMembers(Func<Type, IEnumerable<string>> filter);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        IMapper<TFrom, TTo> IgnoreDestinationMembers(Func<Type, IEnumerable<string>> filter);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="match"></param>
        /// <returns></returns>
        IMapper<TFrom, TTo> MatchMembers(Func<string, string, bool> match);
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="From"></typeparam>
        /// <typeparam name="To"></typeparam>
        /// <param name="converter"></param>
        /// <returns></returns>
        IMapper<TFrom, TTo> ConvertUsing<From, To>(Func<From, To> converter);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="handler"></param>
        /// <returns></returns>
        IMapper<TFrom, TTo> BeforeMap(Action<TFrom, TTo> handler);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="handler"></param>
        /// <returns></returns>
        IMapper<TFrom, TTo> AfterMap(Action<TFrom, TTo> handler);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="from"></param>
        /// <returns></returns>
        TTo Map(TFrom from);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        void Map(TFrom from, ref TTo to);
    }

   /// <summary>
   /// 
   /// </summary>
   [AttributeUsage(AttributeTargets.Field
        | AttributeTargets.Property
        , AllowMultiple=false, Inherited=true)]
	public class SpliteAttribute:Attribute
	{
		/// <summary>
		/// 
		/// </summary>
		public readonly char[] Separator;
		
		/// <summary>
		/// 
		/// </summary>
		/// <param name="separator"></param>
		public SpliteAttribute(params char[] separator)
		{
			if(separator == null || separator.Length == 0)
				throw new ArgumentNullException("separator");
			
			this.Separator= separator;
		}
	}
    
}
